package im.composer.generators;

import org.jaudiolibs.audioservers.AudioConfiguration;

import im.composer.audio.engine.Out;

/**
 * Output sine wave. (Highly inefficient implementation.)
 * 
 * @author Kees van den Doel (kvdoel@cs.ubc.ca) <br>
 *         Adapted by David Zhang (zdl@zdl.hk)
 */

public class Sine extends Out {
	/** Sampling rate in Hertz of Out. */
	private float srate;

	/** Amplitude or volume of sine */
	protected float volume = 1;

	/** Current phase */
	protected float phase = 0;

	/** Freq. in Hertz */
	protected float freq = 440;
	private float oldFreq = freq;

	public static final float TWOPI = (float) (2 * Math.PI);

	public Sine() {
		super();
	}

	public Sine(AudioConfiguration context) {
		super(context);
		srate = context.getSampleRate();
	}

	@Override
	public void setContext(AudioConfiguration context) {
		super.setContext(context);
		srate = context.getSampleRate();
	}

	/**
	 * Set amplitude
	 * 
	 * @param val
	 *            Volume.
	 */
	public void setVolume(float val) {
		volume = val;
	}

	public float getVolume() {
		return volume;
	}

	/**
	 * Set frequency
	 * 
	 * @param f
	 *            frequency.
	 */
	public void setFrequency(float f) {
		freq = f;
	}
	
	public float getFrequency(){
		return freq;
	}

	protected void computeBuffer() {
		int bufsz = getBufferSize();
		float fact = (freq - oldFreq) / (bufsz - 1);
		float f;
		float[] my_buf = new float[getBufferSize()];
		for (int i = 0; i < bufsz; i++) {
			f = oldFreq + fact * i;
			phase += (float) (TWOPI * f / srate);
			my_buf[i] = (float) (volume * Math.sin(phase));
		}
		for (int i = 0; i < buf.getChannelCount(); i++) {
			buf.setRawChannel(i, my_buf);
		}
		while (phase > TWOPI) {
			phase -= TWOPI;
		}

		oldFreq = freq;
	}

}
